#include "uesmemory.h"

#ifdef _DEBUG
ues_memheader_t mem_list =
{
	0,
	0,
	NULL,
	NULL
};
#endif

/*=======================
	Memory functions
=======================*/

// Allocates a memory spot
void*	UES_TagMalloc(unsigned char tag, size_t memsize)
{
	ues_memheader_t *mem;

#ifdef _DEBUG
	if (mem_list.next==NULL)
	{
		LIST_CLEAR(&mem_list)
	}
#endif
	if (tag>TAG_LAST)
		return NULL;
	mem=malloc(memsize+sizeof(ues_memheader_t));
	mem->tag=tag;
#ifdef _DEBUG
	mem->memsize=memsize;
	LIST_APPEND(&mem_list, mem)
#endif
	return mem+1;
}

// Frees tagged memory
int		UES_TagFree(void *memptr)
{
	ues_memheader_t *memhead;
#if (defined(_DEBUG)) && (UES_DEBUGMEMORY==1)
	ues_memheader_t *tmp;

	// In debug we check if this memory really belongs to us
	LIST_FOREACH_BEGIN(&mem_list,tmp)
		if ((tmp+1)==memptr)
			break;
	LIST_FOREACH_END(&mem_list,tmp)
	
	if (tmp==&mem_list)
	{
		c_api->Print("Fatal Error: Tried to free untagged memory\n");
		return 0;
	}
#endif
	memhead=(ues_memheader_t*)(memptr)-1;
#ifdef _DEBUG
	LIST_REMOVE(memhead)
#endif
	free(memhead);
	return 1;
}

// Frees all tagged memory
void	UES_TagFreeAll(unsigned char tag)
{
#ifdef _DEBUG
	ues_memheader_t *tmp;

	LIST_FOREACH_BEGIN(&mem_list,tmp)
		free(tmp);
	LIST_FOREACH_END(&mem_list,tmp)
	LIST_CLEAR(&mem_list);
#endif
}

// Gets total memory usage
size_t	UES_TagGetTotalUsage(unsigned char tag)
{
	size_t mem_usage=0;
#ifdef _DEBUG
	ues_memheader_t *tmp;
	LIST_FOREACH_BEGIN(&mem_list,tmp)
		if (tmp->tag==tag) mem_usage+=tmp->memsize;
	LIST_FOREACH_END(&mem_list,tmp)
#endif
	return mem_usage;
}

// Returns total entries
unsigned int	UES_TagGetNumberOfEntries(unsigned char tag)
{
	unsigned int n=0;
#ifdef _DEBUG
	ues_memheader_t *tmp;

	LIST_FOREACH_BEGIN(&mem_list,tmp)
		if (tmp->tag==tag) n++;
	LIST_FOREACH_END(&mem_list,tmp)
#endif
	return n;
}